package com.qubi.exchange.rest;

import com.alibaba.fastjson.JSONObject;
import com.alicp.jetcache.anno.CacheType;
import com.alicp.jetcache.anno.Cached;
import com.qubi.exchange.biz.ColaExchangeBiz;
import com.qubi.exchange.biz.CommonExchangeBiz;
import com.qubi.exchange.data.MakeOrderParams;
import com.qubi.exchange.message.OrderMessage;
import com.qubi.exchange.security.auth.client.annotation.IgnoreClientToken;
import com.qubi.exchange.security.auth.client.annotation.IgnoreUserToken;
import com.qubi.exchange.security.common.context.BaseContextHandler;
import com.qubi.exchange.security.common.exception.TimeExpireException;
import com.qubi.exchange.security.common.exception.auth.UserTokenException;
import com.qubi.exchange.security.common.msg.AppResponse;
import com.qubi.exchange.websocket.OrderNotifyEntity;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.bouncycastle.pqc.crypto.newhope.NHOtherInfoGenerator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Log4j2
@RestController
@IgnoreClientToken
@RequestMapping("/api/v1")

public class ApiController {


    @Autowired
    CommonExchangeBiz exchangeBiz;
    @Autowired
    ColaExchangeBiz colaExchangeBiz;

    public Map<String, String> parseMap(Map<String, String[]> params) {
        Map<String, String> stringMap = new HashMap<>(10);
        for (String k : params.keySet()) {
            stringMap.put(k, params.get(k)[0]);
        }
        return stringMap;

    }


    public boolean checkKey(Map<String, String> params, String apiKey) {
        var marketUser = colaExchangeBiz.getMarketUserById(apiKey);
        if (marketUser == null) return false;
        String sign = exchangeBiz.makeSign(params, marketUser.getSecret());
        String userSign = params.get("sign");
        log.info("正确签名: "+sign);
        boolean result = sign.equals(userSign);
        if (result) {
            BaseContextHandler.setUserID(marketUser.getUserId());
        }
        return result;

    }

    @RequestMapping("place")
    public AppResponse place(HttpServletRequest request) {
        checkTimestamp(request);
        boolean isCheck = checkSign(request);
        if (!isCheck) {
            throw new UserTokenException("签名错误");
        }

        MakeOrderParams makeOrderParams = new MakeOrderParams();
        makeOrderParams.setNumber(new BigDecimal(request.getParameter("number")));
        makeOrderParams.setPair(request.getParameter("pair"));
        makeOrderParams.setPrice(new BigDecimal(request.getParameter("price")));
        makeOrderParams.setType(request.getParameter("type"));
        return exchangeBiz.placeOrder(makeOrderParams);


    }


    @RequestMapping("placeOrders")
    public AppResponse placeOrders(HttpServletRequest request) {
        checkTimestamp(request);
        boolean isCheck = checkSign(request);
        if (!isCheck) {
            throw new UserTokenException("签名错误");
        }

        List<MakeOrderParams>makeOrderParams=JSONObject.parseArray(request.getParameter("orders"),MakeOrderParams.class);
        List<String>ids=new ArrayList<>();
        for(MakeOrderParams makeOrderParam:makeOrderParams){
            ids.add(exchangeBiz.placeOrder(makeOrderParam).getData().toString());

        }

        return AppResponse.ok().data(ids);

    }

    @RequestMapping("cancel")

    public AppResponse cancel(HttpServletRequest request) {
        checkTimestamp(request);
        boolean isCheck = checkSign(request);
        if (!isCheck) {
            throw new UserTokenException("签名错误");
        }
        Map<String, String> params = new HashMap<>();
        params.put("orderId", request.getParameter("orderId"));
        return exchangeBiz.doCancel(params);

    }

    @RequestMapping("batchCancel")

    public AppResponse batchCancel(HttpServletRequest request) {
        checkTimestamp(request);
        boolean isCheck = checkSign(request);
        if (!isCheck) {
            throw new UserTokenException("签名错误");
        }
        Map<String, String> params = new HashMap<>();
        if (!StringUtils.isEmpty(request.getParameter("pair"))){
            params.put("pair", request.getParameter("pair"));
            exchangeBiz.doCancel(params);
        }else if(!StringUtils.isEmpty(request.getParameter("ids"))){
            List<String> ids = JSONObject.parseArray(request.getParameter("ids"), String.class);
            ids.forEach(x->{
                params.put("orderId",x);
                exchangeBiz.doCancel(params);
            });
        }
        return exchangeBiz.doCancel(params);

    }

    @RequestMapping("detailById")

    public AppResponse detailById(HttpServletRequest request) {
        checkTimestamp(request);
        boolean isCheck = checkSign(request);
        if (!isCheck) {
            throw new UserTokenException("签名错误");
        }
        var order = colaExchangeBiz.getPersonOrderDetail(request.getParameter("orderId"));
        return AppResponse.ok().data(order);


    }

    @RequestMapping("detailByIds")

    public AppResponse detailByIds(HttpServletRequest request) {
        checkTimestamp(request);
        boolean isCheck = checkSign(request);
        if (!isCheck) {
            throw new UserTokenException("签名错误");
        }
        List<String> ids = JSONObject.parseArray(request.getParameter("orderIds"), String.class);
        var orders = new ArrayList<Map<String, Object>>();
        for (String id : ids) {
            var order = colaExchangeBiz.getPersonOrderDetail(id);
            orders.add(order);


        }
        return AppResponse.ok().data(orders);


    }

    public static void main(String[] args) {
        MakeOrderParams makeOrderParams=new MakeOrderParams();
        makeOrderParams.setType("buy");
        makeOrderParams.setPrice(BigDecimal.valueOf(9000));
        makeOrderParams.setNumber(BigDecimal.valueOf(1));
        makeOrderParams.setPair("BTC_USDT");
        System.out.println(JSONObject.toJSONString(makeOrderParams));
    }

    @RequestMapping("entrust")

    public AppResponse entrust(HttpServletRequest request) {
        checkTimestamp(request);
        boolean isCheck = checkSign(request);
        if (!isCheck) {
            throw new UserTokenException("签名错误");
        }
        String pair = request.getParameter("pair");
        int size = Integer.parseInt(request.getParameter("size"));
        int isPending = Integer.parseInt(request.getParameter("isPending"));

        List<OrderMessage> list = exchangeBiz.getOrderMessages(pair, null, size, null, isPending);
        return AppResponse.ok().data(list);
    }

    @RequestMapping("kline")
    public AppResponse kline(String pair, Long start, Long end, Integer limit, String type, String code) {
        return exchangeBiz.getKlines(pair, start, end, limit, type, code);
    }
    @RequestMapping("balance")
    public AppResponse balance(HttpServletRequest request,String coinCode)
    {
        checkTimestamp(request);
        boolean isCheck = checkSign(request);
        if (!isCheck) {
            throw new UserTokenException("签名错误");
        }
        return AppResponse.ok().data(        colaExchangeBiz.getBalance(null,coinCode));

    }
    /**
     * 深度
     *
     * @return
     */
    @RequestMapping("depth")
    @Cached(name = "depth", expire = 2, cacheType = CacheType.LOCAL)
    @IgnoreUserToken
    public AppResponse depth(String pair, Integer length, Integer scale) {
        if (StringUtils.isBlank(pair)) {
            return AppResponse.paramsError();
        }

        return exchangeBiz.getDepthData(pair, length, scale);
    }
    @RequestMapping("trade")
    @Cached(name = "trade", expire = 2, cacheType = CacheType.LOCAL)
    public AppResponse trade(String pair,int size)
    {
        List<OrderNotifyEntity> list = colaExchangeBiz.getMarketOrder(pair, size);
        return AppResponse.ok().data(list);
    }
    public void checkTimestamp(HttpServletRequest request) {
        long now = System.currentTimeMillis();
        long time = Long.parseLong(request.getParameter("timestamp"));
        if (Math.abs(time - now) > 50000 * 1000) throw new TimeExpireException("时间戳过期");
    }

    public boolean checkSign(HttpServletRequest request) {
        var params = request.getParameterMap();
        var paramsMap = parseMap(params);
        String apiKey = paramsMap.get("ApiKey");
        boolean isCheck = checkKey(paramsMap, apiKey);
        return isCheck;
    }


}
